#version 460
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require


#include "../../../../core/shader_binding_ID.h"
#include "../../../../core/shader_std.h"
#include "../../../../core/shader_built_in_functions.h"


layout(location=0) out vec4 outVert;
layout(location=1) out vec4 outNormal;

layout(set = 1, binding = DEF_BINDING_WIDGET_Texture) uniform sampler2D texColor[];

layout(set = 2, binding = DEF_BindID_TextureCube) uniform samplerCube texEnv[];
layout(set = 2, binding = DEF_BindID_TextureShadow) uniform sampler2D texShadow[];
layout(set = 2, binding = DEF_BindID_TexCubeShadow) uniform samplerCube texCubeShadow[];

layout(std140, set = 2, scalar, binding = DEF_BindID_GlobalTextAtt) uniform Buf0 {
	S_GlobalAtt_RasterPostCompositing m_constPush;
	//mat4 m_ProjMatrix;
	//
	//uvec2 m_resolutionRatio;
	//float m_radiusAO;
	//float m_shadowIntensity;
	//float m_depthBias;
	//
	//uint16_t light_Num;
	//uint16_t light_Offset;
	//
	//uint16_t envTex_num;
	//uint16_t envTexAtt_Offset;
};

//每个灯光的阴影图层数量
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_LightIndex) readonly buffer Buf1 {
	S_LightIndex m_LightIndex[];
};

//光投影矩阵
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_PVMatrix) readonly buffer Buf3 {
	mat4 m_LightArea_PVMatrix[];
};

//区域光属性
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_AreaLight) readonly buffer Buf2 {
	S_LightArea m_LightArea[];
};



layout(location = 0) in vec3 inEyeDir;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec4 inVert;

layout(early_fragment_tests) in;

void main(void) {
	
	vec3 w = vec3(0.2125,0.7154,0.0721);
	vec3 viewDir = normalize(inEyeDir);
	vec3 rv = reflect(viewDir, inNormal);

	float s = 0;
	float a = 0;
	//outColor += texture(texEnv[0], rv) * 0.8;
	//outColor += texture(texEnv[0], normalize(inEyeDir));
	//outColor += texture(texEnv[0], inNormal);
	//outColor.xyz = inNormal;
	//if(inVert.z < 0){
	//	//outColor.xyz += normalize(inVert);
	//	outColor.z += 0.1;
	//}else{
	//	
	//}
	//outColor += texture(texEnv[nonuniformEXT(0)], normalize(inVert)) * 0.8;

	outVert = vec4(inVert.xyz, gl_FragCoord.w);
	//outVert = vec4(vec3(gl_FragCoord.xyz * gl_FragCoord.w), 1);
	outNormal = vec4(-normalize(-rv + viewDir), gl_FragCoord.w);

	return;
	
	vec3 irradiance = vec3(0);
	vec3 albedo = vec3(0.4,0.2,0.1);
	vec3 metallicRoughness = vec3(0.1);
	vec3 F0 = vec3(0.04);

	//切线法线
	vec3 N = inNormal;
	vec3 R = reflect(normalize(inEyeDir), N);


	vec3 lightColor = vec3(0.0001);
	

	for(uint i = 0; i < uint(m_constPush.light_Num); ++i){
		S_LightIndex light = m_LightIndex[m_constPush.light_Offset + i];

		//outColor.xyz += vec3(0.1);

		switch(uint(light.m_lightType)){
			case DEF_ObType_Ligth_Parallel : {
				break;
			}
			case DEF_ObType_Ligth_Point : {
				break;
			}
			case DEF_ObType_Ligth_Area : {
				S_LightArea area = m_LightArea[light.m_attIndex];
				mat4 projMatrix0 = m_LightArea_PVMatrix[light.m_matrixIndex];
				vec4 shadowVert = projMatrix0 * inVert;
				//shadowVert.xyz /= inVert.w;
				
				shadowVert.xy += 1;
				shadowVert.xy *= 0.5;
				float z = texture(texShadow[light.m_shadowTexIndex], shadowVert.xy).r;

				//float r = (shadowVert.z - z);
				shadowVert.z -= 0.0001;
				
				a = 0;
				float ld = max(dot(N, -area.m_dir), 0) * area.m_intensity;
				//if(r < 0.008) r += 1.1;
				float r = area.m_diffusivity * 0.01;
				//float m = 0;

				float maxDis = 0;
				for(int x = -1; x <= 1; ++x){
					for(int y = -1; y <= 1; ++y){
						float z1 = texture(texShadow[light.m_shadowTexIndex], shadowVert.xy + (vec2(x, y) * r * 0.3) ).r;
						maxDis = max(maxDis, shadowVert.z - z1);
					}
				}
				int lightAreaIt = 2;
				for(int x = -lightAreaIt; x <= lightAreaIt; ++x){
					for(int y = -lightAreaIt; y <= lightAreaIt; ++y){
						//float r1 = clamp(0, 1, r) * 0.01;
						float r1 = maxDis * r * 5;
						vec2 d = vec2(x, y);

						float z1 = texture(texShadow[light.m_shadowTexIndex], shadowVert.xy + (d * r1) ).r;
						
						r1 = clamp(shadowVert.z - z1, 0, 0.01);
						a += r1;
						//m += step(shadowVert.z - z1, 0.002);
						//m += step(0.002, shadowVert.z - z1);
						//float a = clamp(0.001, 0.1, max(shadowVert.z - z1, 0));
						//m += smoothstep(0, 1, a / 0.01);
						//m += a * 10;
					}
				}
				//m *= 0.04;
				//s -= min(m, 1);
				//s += area.m_diffusivity;
				//s += area.m_dis;
				s += min(a * a / lightAreaIt * 10, 1);
				
				
				//s += (1 - smoothstep(0.001, 0.05, m / 0.05)) * 0.5;
				vec3 lightIntensity = area.m_color * ld;
				lightColor += lightIntensity;

				//vec3 rv = reflect(inEyeDir, N);
				vec3 L = normalize(area.m_pos - inVert.xyz);
				
				//lightColor += pow(max(dot(R, L), 0) * max(dot(N, -area.m_dir), 0), 10) * 0.01;
				//lightColor = max(lightColor, vec3(0.1));
				//float b = step(0.0001, s.r);
				//float c = 1 - sign(a);
				//z = z gl_FragDepth >;
				//if(gl_FragCoord.y > 700/2){
				//	outColor.yz += vec2(shadowVert.z - z >= 0.01);
				//}else{
				//	outColor.yz += vec2(s1);
				//}
				//float dfx = dFdx(gl_FragCoord.x);
				//float dfy = dFdy(gl_FragCoord.y);
				//outColor.yz = vec2(1) * (1 - s) * 0.5;
				
				//if(i==0){
				//	if(gl_FragCoord.x < 1280/2){
				//	}
				//}else{
				//	if(gl_FragCoord.x >= 1280/2){
				//	}
				//}
				//outColor.xyz = vec3(shadowVert.xyz);
				//outColor.yz += vec2(shadowVert.z - z <= 0.01);
				break;
			}
			case DEF_ObType_Ligth_Spot : {
				break;
			}
		}
		//outColor.xyz = inVert.xyz;
		
	}


	float sampleDelta = 0.1;
	int nrSamples = 0; 
	for(float phi = 0.0; phi < 2.0 * M_PI; phi += sampleDelta) {
		for(float theta = 0.5; theta < 0.5 * M_PI; theta += sampleDelta) {
			vec3 SampleVec = f_SphereSampling(vec2(theta, phi));
			//vec3 SampleVec = f_SphereSampling2(vec2(theta, phi));
			
			//SampleVec = f_SphereSampling_toWorld2(SampleVec, N);
			SampleVec = f_SphereSampling_toWorld(SampleVec, N);
			irradiance += texture(texEnv[0], SampleVec).rgb * cos(theta) * cos(theta);
			//irradiance += texture(texEnv[0], N).rgb * cos(theta) * cos(theta);
			//irradiance += texture(texEnv[0], N).rgb;
			//irradiance += SampleVec;
			++nrSamples;
		}
		//break;
	}
	irradiance = M_PI * irradiance * (1.0 / float(nrSamples));
	//irradiance = irradiance;
	//f_SphereSampling_toWorld(TangentSample, rv);
	//irradiance += texture(texEnv[0], N).rgb;
	

	s = 1 - clamp(s, 0, 1);
	if (gl_SampleID == 0) { 
		//imageStore(GBuffer_Image[DEF_GBuffer_Vert], ivec2(gl_FragCoord), vec4(inVert.xyz, gl_FragDepth));
		//imageStore(GBuffer_Image[DEF_GBuffer_Normal], ivec2(gl_FragCoord), vec4(inNormal, s));

		
	}
	//barriers();
	


	irradiance *= vec3(s);
	//outColor.xyz = irradiance + lightColor * s;
	//outColor.xyz = irradiance + lightColor;
	//outColor.xyz = lightColor * vec3(s);
	//outColor.xyz += irradiance;

	
	//outColor.xyz += normalize(inEyeDir);
	//outColor.xyz += normalize(inNormal);
	//outColor.xyz += normalize(rv) * 0.3;
	//outColor += texture(texEnv[0], vec3(1,0,0));
}



